#include <ESP8266WiFi.h>
#include <WiFiClient.h>
#include <Wire.h>

/*
* WIFI
*/
//WIFI名称，区分大小写，不要写错
#define DEFAULT_STASSID  "hehe"
//WIFI密码
#define DEFAULT_STAPSW "19991205zou"
//用户私钥，可在控制台获取,修改为自己的UID

/*
* 巴法云TCP
*/
//巴法云服务器地址默认即可
#define TCP_SERVER_ADDR "bemfa.com"
//服务器端口//TCP创客云端口8344//TCP设备云端口8340
#define TCP_SERVER_PORT "8344"
// 话题配置
String UID = "";  // 需要配置
String TOPIC = "AXL345";
//设置上传速率1s
#define upDataTime 1*1000
//设置心跳
#define upheartTime 30*1000
#define KEEPALIVEATIME 30*1000
int intNumber = 0;
//最大字节数
#define MAX_PACKETSIZE 51
//tcp客户端相关初始化，默认即可
WiFiClient TCPclient;
String TcpClient_Buff = "";
unsigned int TcpClient_BuffIndex = 0;
unsigned long TcpClient_preTick = 0;
unsigned long preHeartTick = 0;//心跳
unsigned long predataTick = 0;//数据时间
unsigned long preTCPStartTick = 0;//连接
bool preTCPConnected = false;


/*
* IIC 的配置
*/

// ADXL345 I2C address is 0x53(83)
#define Addr 0x53

const uint8_t scl = D1; //D1
const uint8_t sda = D2; //D2
   
float xAccl, yAccl, zAccl;


// IIC 采集数据
void handleroot()
{
    unsigned int data[6];
    // 启动I2C传输
    Wire.beginTransmission(Addr);
    // 选择带宽速率寄存器
    Wire.write(0x2C);
    // Normal mode, Output data rate = 100 Hz
    Wire.write(0x0A);
    // 停止I2C传输
    Wire.endTransmission();

    // 启动I2C传输
    Wire.beginTransmission(Addr);
    // 选择功率控制寄存器
    Wire.write(0x2D);
    // Auto-sleep disable
    Wire.write(0x08);
    // 停止I2C传输
    Wire.endTransmission();

    // 启动I2C传输
    Wire.beginTransmission(Addr);
    // 选择数据格式寄存器
    Wire.write(0x31);
    // Self test disabled, 4-wire interface, Full resolution, Range = +/-2g
    Wire.write(0x08);
    // 停止I2C传输
    Wire.endTransmission();

    delay(300);
    for (int i = 0; i < 6; i++)
    {
    // 启动I2C传输
    Wire.beginTransmission(Addr);
    // 选择数据寄存器
    Wire.write((50 + i));
    // //停止I2C传输
    Wire.endTransmission();
    // 读取1字节数据
    Wire.requestFrom(Addr, 1);
    // 读取6字节数据
    // xAccl lsb, xAccl msb, yAccl lsb, yAccl msb, zAccl lsb, zAccl msb
    if (Wire.available() == 1)
    {
    data[i] = Wire.read();
    }
    }
    // 将数据转换为10位
    int xAccl = (((data[1] & 0x03) * 256) + data[0]);
    if (xAccl > 511)
        {
        xAccl -= 1024;
        }
    int yAccl = (((data[3] & 0x03) * 256) + data[2]);
    if (yAccl > 511)
        {
        yAccl -= 1024;
        }
    int zAccl = (((data[5] & 0x03) * 256) + data[4]);
    if (zAccl > 511)
        {
        zAccl -= 1024;
        }
    // 串口输出传感器数据
    Serial.print("Acceleration in X-Axis : ");
    Serial.println(xAccl);
    Serial.print("Acceleration in Y-Axis : ");
    Serial.println(yAccl);
    Serial.print("Acceleration in Z-Axis : ");
    Serial.println(zAccl);
    delay(500);
      
    String  tcpTemp = "cmd=2&uid=" + UID + "&topic=" + TOPIC + "&msg=#X#"+String(xAccl) +"#y#"+String(yAccl)+"#z#"+String(zAccl)+ "#\r\n";; //构建发布指令
    sendtoTCPServer(tcpTemp); //发送订阅指令
    tcpTemp = ""; //清空
}

// 初始化wifi
void startSTA(){
  WiFi.disconnect();
  WiFi.mode(WIFI_STA);
  WiFi.begin(DEFAULT_STASSID, DEFAULT_STAPSW);

}
// 连接网络
void doWiFiTick(){
  static bool startSTAFlag = false;
  static bool taskStarted = false;
  static uint32_t lastWiFiCheckTick = 0;

  if (!startSTAFlag) {
    startSTAFlag = true;
    startSTA();
    Serial.printf("Heap size:%d\r\n", ESP.getFreeHeap());
  }

  //未连接1s重连
  if ( WiFi.status() != WL_CONNECTED ) {
    if (millis() - lastWiFiCheckTick > 1000) {
      lastWiFiCheckTick = millis();
    }
  }
  //连接成功建立
  else {
    if (taskStarted == false) {
      taskStarted = true;
      Serial.print("\r\nGet IP Address: ");
      Serial.println(WiFi.localIP());
      startTCPClient();
    }
  }
}
// 初始化TCP
void startTCPClient(){
  if(TCPclient.connect(TCP_SERVER_ADDR, atoi(TCP_SERVER_PORT))){
    Serial.print("\nConnected to server:");
    Serial.printf("%s:%d\r\n",TCP_SERVER_ADDR,atoi(TCP_SERVER_PORT));

    String tcpTemp="";  //初始化字符串
    tcpTemp = "cmd=1&uid="+UID+"&topic="+TOPIC+"\r\n"; //构建订阅指令
    sendtoTCPServer(tcpTemp); //发送订阅指令
    tcpTemp="";//清空
    
    preTCPConnected = true;
    preHeartTick = millis();
    predataTick = millis();
    TCPclient.setNoDelay(true);
    
  }
  else{
    Serial.print("Failed connected to server:");
    Serial.println(TCP_SERVER_ADDR);
    TCPclient.stop();
    preTCPConnected = false;
  }
  preTCPStartTick = millis();
}
// 发送数据
void sendtoTCPServer(String p){
  
  if (!TCPclient.connected()) 
  {
    Serial.println("Client is not readly");
    return;
  }
  TCPclient.print(p);
  Serial.println("[Send to TCPServer]:String");
  Serial.println(p);
}
// 检查和发送数据
void doTCPClientTick(){
 //检查是否断开，断开后重连
   if(WiFi.status() != WL_CONNECTED) return;

  if (!TCPclient.connected()) {//断开重连

  if(preTCPConnected == true){

    preTCPConnected = false;
    preTCPStartTick = millis();
    Serial.println();
    Serial.println("TCP Client disconnected.");
    TCPclient.stop();
  }
  else if(millis() - preTCPStartTick > 1*1000)//重新连接
    startTCPClient();
  }
  else
  {
    if (TCPclient.available()) {//收数据
      char c =TCPclient.read();
      TcpClient_Buff +=c;
      TcpClient_BuffIndex++;
      TcpClient_preTick = millis();
      
      if(TcpClient_BuffIndex>=MAX_PACKETSIZE - 1){
        TcpClient_BuffIndex = MAX_PACKETSIZE-2;
        TcpClient_preTick = TcpClient_preTick - 200;
      }
      preHeartTick = millis();
      predataTick = millis();
    }
    if(millis() - preHeartTick >= KEEPALIVEATIME){//保持心跳
      preHeartTick = millis();
      Serial.println("--Keep alive:");
      sendtoTCPServer("cmd=0&msg=keep\r\n");
    }
     
     if(millis() - preHeartTick >= upheartTime){//发送心跳
      preHeartTick = millis();
      
      String upstr = "";
      upstr = "cmd=0&msg=ping\r\n";
      intNumber++;
      sendtoTCPServer(upstr);
      upstr = "";
      
    }
  }
}

void setup()
{
    // 初始化I2C通信作为主机
    Wire.begin(sda, scl);
    // 初始化串口波特率
    Serial.begin(115200);
}
void loop()
{
    doWiFiTick();
    doTCPClientTick();
    delay(500); 
    handleroot();  // 采集数据
    
    
}
